import { GameLoop } from './core/GameLoop.js';
import { EventBus } from './core/EventBus.js';
import { Board } from './world/Board.js';
import { Renderer } from './render/Renderer.js';
import { SunManager } from './systems/SunManager.js';
import { Plant } from './entities/Plant.js';
import { CooldownManager } from './systems/CooldownManager.js';
import { WaveManager } from './systems/WaveManager.js';
import { Zombie } from './entities/Zombie.js';
import { Projectile } from './entities/Projectile.js';
import { Tile } from './world/Tile.js';

const canvas = document.getElementById('game');
const ctx = canvas.getContext('2d');

// Core services
const bus = new EventBus();
const board = new Board(5, 9); // 5 行 9 列基本草地（默认，稍后由关卡覆盖）
const sun = new SunManager(bus, 50);
const cooldowns = new CooldownManager();

// 游戏状态
const state = {
  cards: [],
  selectedCardIndex: -1,
  projectiles: [],
  zombies: [],
  status: 'menu',
  settings: { showHealthBars: false, pixelSmooth: false },
};

const renderer = new Renderer(ctx, board, { bus, sun, cooldowns, state });

// 加载配置
let plantsConfig = {};
let zombiesConfig = {};
let levelConfig = null;
Promise.all([
  fetch('./configs/entities/plants.json').then(r => r.json()).then(j => { plantsConfig = j; }),
  fetch('./configs/entities/zombies.json').then(r => r.json()).then(j => { zombiesConfig = j; }),
  fetch('./configs/levels/level1.json').then(r => r.json()).then(j => { levelConfig = j; })
]).then(() => {
  // 应用关卡设置
  board.rows = levelConfig.rows; board.cols = levelConfig.cols;
  board.tiles = Array.from({ length: board.rows }, () => Array.from({ length: board.cols }, () => new Tile('grass')));
  sun.suns = levelConfig.initialSun;
  // 卡片栏
  state.cards = levelConfig.availableCards.map(id => ({ id, name: plantsConfig[id]?.name || id, cost: plantsConfig[id]?.cost || 0 }));
  // 冷却初始化：默认就绪
  levelConfig.availableCards.forEach(id => cooldowns.set(`card:${id}`, 0));
  // 波次管理
  const waveScript = levelConfig.waves || [];
  const wm = new WaveManager(waveScript, (lane, type) => {
    const cfg = zombiesConfig[type] || { hp: 200, speed: 20 };
    // 僵尸出生在对应行的最右侧
    const { x: cx, y, cellW, gridW } = renderer.gridToPixel(lane, board.cols - 1);
    const startX = renderer.padding + gridW + renderer.padding - cellW * 0.2; // 网格右外一点
    const z = new Zombie();
    z.hp = Number(cfg.hp) || 200;
    z.maxHp = Number(cfg.hp) || 200;
    z.speed = Number(cfg.speed) || 20;
    z.damage = Number(cfg.damage) || 20;
    z.row = lane;
    z.x = startX;
    z.y = y;
    z.type = type;
    state.zombies.push(z);
  });
  // 将 WaveManager 纳入更新
  extraUpdaters.push(wm);
  state.waveManager = wm;
  // 渲染器可访问实体配置，用于血条比例回退
  renderer.services.configs = { plants: plantsConfig, zombies: zombiesConfig };
});

// 额外更新器集合（波次、碰撞等）
const extraUpdaters = [];

function update(dt) {
  // 若已胜负，则暂停更新
  if (state.status !== 'playing') return;
  // 更新核心系统
  sun.update(dt);

  // 植物行为：发射与产阳光
  for (let r = 0; r < board.rows; r++) {
    for (let c = 0; c < board.cols; c++) {
      const t = board.tiles[r][c];
      const plant = t.plant;
      if (!plant) continue;
      const cfg = plantsConfig[plant.kind || ''] || null;
      if (!cfg) continue;
      plant._t = (plant._t || 0) + dt;
      // 发射
      if (cfg.projectile && cfg.attackRateMs) {
        const rate = cfg.attackRateMs;
        const burst = cfg.burst || 1;
        if (plant._t >= rate) {
          plant._t = 0;
          const { x, y } = renderer.gridToPixel(r, c);
          for (let k = 0; k < burst; k++) {
            const p = new Projectile();
            p.type = cfg.projectile;
            p.damage = cfg.damage || 20;
            p.speed = 240;
            p.x = x + 10 + k * 6; // 双发稍微错位
            p.y = y;
            p.row = r;
            state.projectiles.push(p);
          }
        }
      }
      // 产阳光
      if (cfg.produceSun && cfg.produceRateMs) {
        plant._sunT = (plant._sunT || 0) + dt;
        if (plant._sunT >= cfg.produceRateMs) {
          plant._sunT = 0;
          sun.add(cfg.produceSun);
        }
      }
    }
  }

  // 投射物移动与碰撞
  for (let i = state.projectiles.length - 1; i >= 0; i--) {
    const p = state.projectiles[i];
    p.x += p.speed * (dt / 1000);
    // 超出右边界则移除
    const metrics = renderer.gridToPixel(0, board.cols - 1);
    if (p.x > renderer.padding + metrics.gridW + 16) { state.projectiles.splice(i, 1); continue; }
    // 与僵尸碰撞（同一行，x接近）
    for (let j = state.zombies.length - 1; j >= 0; j--) {
      const z = state.zombies[j];
      if (z.row !== p.row) continue;
      if (Math.abs(z.x - p.x) < metrics.cellW * 0.35) {
        const dmg = Number(p.damage) || 0;
        z.hp = Math.max(0, (z.hp ?? 0) - dmg);
        // 命中即判死：在僵尸更新循环之前就移除
        if ((z.hp ?? 0) <= 0) { state.zombies.splice(j, 1); }
        // 寒冰减速
        if (p.type === 'snowpea') {
          z._slowT = Math.max(z._slowT || 0, 3000);
          z._slowFactor = 0.5;
        }
        state.projectiles.splice(i, 1);
        break;
      }
    }
  }

  // 僵尸移动与啃食（受寒冰减速影响）
  for (let i = state.zombies.length - 1; i >= 0; i--) {
    const z = state.zombies[i];
    // 如果与某格中心对齐且该格有植物，则进入啃食
    let eatingCell = null;
    const base = renderer.gridToPixel(z.row, 0);
    for (let c = 0; c < board.cols; c++) {
      const cell = renderer.gridToPixel(z.row, c);
      const half = cell.cellW * 0.5;
      if (Math.abs(z.x - cell.x) <= half * 0.6) { // 处于该格中心附近
        const t = board.tiles[z.row][c];
        if (t.plant) { eatingCell = { row: z.row, col: c }; }
        break;
      }
    }
    if (eatingCell) {
      z._eating = eatingCell;
    } else {
      z._eating = null;
    }

    if (z._eating) {
      const t = board.tiles[z._eating.row][z._eating.col];
      const plant = t.plant;
      if (plant) {
        const dps = z.damage || 20;
        plant.hp = Math.max(0, (plant.hp ?? 300) - dps * (dt / 1000));
        // 植物死亡则移除并恢复移动
        if (plant.hp <= 0) { t.plant = null; z._eating = null; }
      } else {
        z._eating = null;
      }
    } else {
      const slow = z._slowT && z._slowT > 0 ? (z._slowFactor || 0.5) : 1;
      if (z._slowT && z._slowT > 0) z._slowT -= dt;
      z.x -= (z.speed * slow) * (dt / 1000);
    }

    if ((z.hp ?? 0) <= 0) { state.zombies.splice(i, 1); continue; }
    // 失败判定：僵尸越过最左边界
    const leftBound = renderer.padding + 8;
    if (z.x < leftBound) { state.status = 'lost'; break; }
  }

  // 额外更新器
  extraUpdaters.forEach(u => u.update?.(dt));

  // 胜利判定：波次完成且场上无僵尸
  if (state.waveManager?.isComplete() && state.zombies.length === 0) {
    state.status = 'won';
  }
}

function render() {
  renderer.render();
}

const loop = new GameLoop(update, render);
loop.attachBus(bus);
loop.start();

// 每 2 秒增加阳光（示例）
let acc = 0;
bus.on('loop:tick', (dt) => {
  acc += dt;
  if (acc >= 2000) { acc = 0; sun.add(25); }
});

// 点击交互：先命中卡片栏；否则为种植
canvas.addEventListener('click', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;

  // 菜单/设置屏幕点击优先处理
  if (state.status === 'menu') {
    const id = renderer.pickMenu?.(x, y);
    if (id === 'start') { state.status = 'playing'; return; }
    if (id === 'settings') { state.status = 'settings'; return; }
    return;
  }
  if (state.status === 'settings') {
    const id = renderer.pickSettings?.(x, y);
    if (id === 'back') { state.status = 'menu'; return; }
    if (id === 'toggle_health') { state.settings.showHealthBars = !state.settings.showHealthBars; return; }
    if (id === 'toggle_smooth') { state.settings.pixelSmooth = !state.settings.pixelSmooth; return; }
    return;
  }

  // 顶部控制按钮（暂停/继续、结束）
  const ctrl = renderer.pickControls?.(x, y);
  if (ctrl === 'pause_toggle') {
    state.status = state.status === 'paused' ? 'playing' : 'paused';
    return;
  }
  if (ctrl === 'end_game') {
    // 重置到主菜单并清理状态
    state.status = 'menu';
    // 清空实体与网格植物
    state.projectiles = [];
    state.zombies = [];
    for (let r = 0; r < board.rows; r++) {
      for (let c = 0; c < board.cols; c++) { board.tiles[r][c].plant = null; }
    }
    // 重置阳光与冷却
    if (levelConfig) sun.suns = levelConfig.initialSun;
    cooldowns.clear?.();
    levelConfig?.availableCards?.forEach(id => cooldowns.set(`card:${id}`, 0));
    // 重置波次
    if (state.waveManager?.reset) state.waveManager.reset();
    // 取消选中卡
    state.selectedCardIndex = -1;
    return;
  }

  // 选卡
  const ci = renderer.pickCard(x, y);
  if (ci >= 0) { state.selectedCardIndex = ci; return; }
  // 种植
  const { row, col } = renderer.pickGrid(x, y);
  const selected = state.cards[state.selectedCardIndex];
  if (!selected) return;
  const cfg = plantsConfig[selected.id];
  const plant = new Plant();
  plant.kind = selected.id;
  plant.cost = cfg.cost;
  plant.allowedTileTypes = cfg.allowedTileTypes || ['grass'];
  plant.hp = cfg.hp || plant.hp;
  plant.maxHp = plant.hp;
  const cdReady = cooldowns.ready(`card:${selected.id}`);
  if (board.canPlace(row, col, plant) && cdReady && sun.spend(plant.cost)) {
    board.place(row, col, plant);
    cooldowns.set(`card:${selected.id}`, cfg.cooldownMs || 5000);
  }
});